﻿package com.pandemicode.framework.localization {
	import com.pandemicode.framework.controls.LocalizableTextField;
	import com.pandemicode.framework.utils.Filter;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import org.osflash.signals.Signal;
	
	/**
	* @author Michael Lawrence
	* @timestamp 9/22/2008 4:10 PM
	*/
	public dynamic class LocaleManager {
		private var _locales:Array;
		private var _currentLocale:Locale;
		private var _xmlPath:String = "locale/$language/strings.xml";
		private var _fontPath:String = "locale/$language/font.swf";
		private var _textFields:Array;
		
		private var _changed:Signal;
		private var _loaded:Signal;
		
		public function get changed():Signal { return this._changed; }
		public function get loaded():Signal { return this._loaded; }
		
		/**
		 * The current locale being used.
		 */
		public function get currentLocale():Locale { return this._currentLocale; }
		public function set currentLocale(value:Locale):void {
			if (value == null || !this.localeIsLoaded(value.language))
				throw new Error("Locale '" + value + "' is not loaded");
			else {
				this._currentLocale = value;
				this._changed.dispatch(this._currentLocale);
			}
		}
		
		/**
		 * The current locale language being used.
		 */
		public function get currentLocaleLanguage():String { return this._currentLocale.language; }
		public function set currentLocaleLanguage(value:String):void {
			if (value == null || !this.localeIsLoaded(value))
				throw new Error("Locale '" + value + "' is not loaded");
			else this.currentLocale = this.getLocale(value);
		}
		
		/**
		 * The path to load the xml from ($language is replaced with the specified langauge).
		 */
		public function get xmlPath():String { return this._xmlPath; }
		public function set xmlPath(value:String):void {
			this._xmlPath = value;
		}
		
		/**
		 * The path to load the font from ($language is replaced with the specified langauge).
		 */
		public function get fontPath():String { return this._fontPath; }
		public function set fontPath(value:String):void {
			this._fontPath = value;
		}
		
		private static const _instance:LocaleManager = new LocaleManager(SingletonLock);
		/**
		 * The singleton instance.
		 */
		public static function get instance():LocaleManager {
			return _instance;
		}
		
		/**
		 * Singleton that manages the loading, string fetching, and changing of locales.  Use LocaleManager.instance.
		 * @param	lock	The singleton lock.
		 */
		public function LocaleManager(lock:Class) {
			if (lock != SingletonLock)
				throw new Error("Invalid Singleton access. Use LocaleManager.instance.");
				
			this._changed = new Signal(Locale);
			this._loaded = new Signal(Locale);
			
			this._locales = new Array();
			this._textFields = new Array();
		}
		
		/**
		 * Loads the specified locale.
		 * @param	locale	The language code of the locale to load.
		 */
		public function loadLocale(locale:String):void {
			if(!this.localeExists(locale)) {
				var loc:Locale = new Locale(locale, this._xmlPath, this._fontPath);
				loc.loaded.add(this._onLocaleLoaded);
				loc.load();
			} else {
				throw new Error("Locale " + locale + " already exists.");
			}
		}
		
		/**
		 * Checks if the specified locale exists.
		 * @param	locale	The language code of the locale to check.
		 * @return	Returns whether the specified locale exists.
		 */
		public function localeExists(locale:String):Boolean {
			return this.getLocale(locale) != null;
		}
		
		/**
		 * Checks if the specified locale is loaded.
		 * @param	locale	The language code of the locale to check.
		 * @return	Returns whether the specified locale is loaded.
		 */
		public function localeIsLoaded(locale:String):Boolean {
			if (this.localeExists(locale))
				return this.getLocale(locale).isLoaded;
			return false;
		}
		
		/**
		 * Returns the specified locale.
		 * @param	locale	The locale to retrieve.
		 * @return	Returns the specified locale.
		 */
		public function getLocale(locale:String):Locale {
			for each(var loc:Locale in this.locales)
				if (loc.language == locale) return loc;
			return null;
		}
		
		/**
		 * Returns a string by the specified id from the current locale.
		 * @param	id	The id to retrieve the string with.
		 * @return	Returns a string by the specified id from the current locale.
		 */
		public function getString(id:String):String {
			if (this._currentLocale != null)
				return this.currentLocale.getString(id);
			return null;
		}
		
		/**
		 * Occurs once the locale is finished loading.
		 * @param	locale	The locale that was loaded.
		 */
		private function _onLocaleLoaded(locale:Locale):void {
			this._locales.push(locale);
			
			if (this._currentLocale == null)
				this._currentLocale = locale;
				
			this._loaded.dispatch(locale);
		}
	}
}

/*
* This is a private class declared outside of the package
* that is only accessible to classes inside of the GameTimer.as
* file.  Because of that, no outside code is able to get a
* reference to this class to pass to the constructor, which
* enables us to prevent outside instantiation.
*/
class SingletonLock { }
